const moment = require('moment')
const mongoose = require('mongoose')
// schema封装到文件
const customSchemas = require('../../schemas/adminSchemas/schema')
const Schema = mongoose.Schema
mongoose.connect('mongodb://localhost/moba', {
    useNewUrlParser: true
})
mongoose.set('useFindAndModify', false)
mongoose.Promise = global.Promise


// Functions
// =============== 通用CRUD ===================
// 该处为通用的CRUD，适用于最普通的列表增删改查。
// 第一个参数都为model，是从schema文件中引入的。

// 通用查询——支持普通字段查询 多条件联合查询 模糊查询 分页功能
function getCommonList(model, queryList, body) {
    return new Promise((resolve, reject) => {
        let allRecords;
        let _filter = {};
        // 如果定义该查询方法时需要查询参数（queryList不为空），那么find时，带上参数_filter。
        // 生成filter，用于多条件查询。
        if (queryList.length > 0) {
            // 这里需要注意前端传了哪些字段就去设置哪些规则，若是没传或者传空就不去设置规则。
            let filterArray = []
            queryList.forEach(item => {
                console.log("查询参数对应列表", item, body[item])
                if (body[item] == undefined || body[item] == '') {
                    // doNothing，不去为filter中设置规则。
                } else {
                    filterArray.push({
                        [item]: {
                            $regex: new RegExp(body[item], "i")
                        }
                    })
                }
            })
            console.log("查询时生成的filter", filterArray)
            // 判断一下如果前端啥都没传或者都传空，filter保持空结构。
            filterArray.length > 0 ? _filter = _filter = {
                $and: filterArray
            } : ''

            allRecords = model.find(_filter)
        } else {
            allRecords = model.find()
        }

        let currentPage = Number(body.currentPage);
        let recordPerPage = Number(body.recordPerPage);
        // 设置分页相关条件
        allRecords.skip((currentPage - 1) * recordPerPage);
        allRecords.limit(recordPerPage);


        // 分页条件设置完成后，再调用exec开始执行查询
        allRecords.exec((err, ret) => {
            if (err) {
                reject(err);
            } else {
                // 自定义返回结构，再执行一次find是为了获取total数据量
                model.find(_filter, (err, result) => {
                    if (err) return reject(err)
                    jsonArray = {
                        list: ret,
                        total: result.length
                    };
                    resolve(jsonArray)
                });
            }
        })
    })
}

// 通用添加 物品的createTime和lastModifyTime字段由我们加上 默认都是当前时间
function createCommonData(model, body) {
    return new Promise((resolve, reject) => {
        console.log(model)
        body.createTime = moment().format("YYYY-MM-DD HH:mm:ss");
        body.lastModifyTime = moment().format("YYYY-MM-DD HH:mm:ss"),
            new model(body).save(err => {
                if (err) {
                    console.log(err.message)
                    if (/duplicate/.test(err.message) === true) {
                        reject("规定的字段不能重复！")
                    } else {
                        reject(err)
                    }
                } else {
                    resolve()
                }
            })
    })
}

// 通用编辑
// editableAttrs代表允许编辑的字段。是一个数组.
function editCommonData(model, editableAttrs, body) {
    return new Promise((res, rej) => {
        if (body.id === undefined) rej("ID不能为空!")
        // 根据前端body传来的数据，对应出有实际值的允许修改的字段。
        let editList = editableAttrs.filter(item => {
            return body[item] !== undefined && body[item] !== ''
        })
        // 先设置$set的结构，不管有没有参数只要指定了id调了接口就设置lastModifyTime字段。
        let setoptions = {
            $set: {
                "lastModifyTime": moment().format("YYYY-MM-DD HH:mm:ss"),
            }
        }
        // 如果有可以修改的参数，就给$set里添加。
        if(editList.length > 0){
            editList.forEach(item => {
                setoptions.$set[item] = body[item]
            })
        }
        console.log("编辑时即将编辑的字段" , setoptions.$set)

        model.findByIdAndUpdate(body.id, setoptions, (err, docs) => {
            if (err) return rej(err)
            res()
        })
    })
}

// 通用删除
function deleteCommonData(model, body) {
    return new Promise((resolve, reject) => {
        if (body.id === undefined || body.id === '') reject("ID不能为空!")
        model.findByIdAndRemove(body.id, (err, docs) => {
            if (err) {
                reject(err)
            } else {
                resolve()
            }
        })
    })
}

// =============== 分类管理 树结构 特殊处理 ==============
// 查询分类列表，支持分页,支持条件查询（模糊查询）
// 首先拿到所有数据，通过skip指定条数据后限定返回的limit数据，再exec得到处理后的结果。
function getCategoryList(body) {
    return new Promise((resolve, reject) => {
        // 与直接进行查询并处理回调函数不同的是，先定义查询动作，但不执行查询
        // 根据传参判断是否有name查询条件，来处理不同的find。
        let reg = new RegExp(body.categoryName, "i");
        let _filter = {
            //多字段匹配
            $or: [{
                categoryName: {
                    $regex: reg
                }
            }, ]
        }
        let allRecords = (body.categoryName == undefined || body.categoryName == '') ? customSchemas.categoryModel.find() : customSchemas.categoryModel.find(_filter);
        let currentPage = Number(body.currentPage);
        let recordPerPage = Number(body.recordPerPage);
        // 设置条件
        allRecords.skip((currentPage - 1) * recordPerPage);
        allRecords.limit(recordPerPage);

        // 条件设置完成后，再调用exec开始执行查询
        allRecords.exec((err, ret) => {
            if (err) {
                reject(err);
            } else {
                // 自定义返回结构，再执行一次find是为了获取total数据量
                let reg = new RegExp(body.categoryName, "i");
                console.log(body.categoryName)

                customSchemas.categoryModel.find((body.categoryName == undefined || body.categoryName == '') ? {} : _filter, (err, result) => {
                    if (err) return reject(err)
                    jsonArray = {
                        list: ret,
                        total: result.length
                    };
                    resolve(jsonArray)
                });
            }
        })
    })
}

// 添加数据 根据type区分根节点和叶子节点 规定层级最多为2.
// type0 根节点  type1 叶子节点（需要传入parentId）
function createCategory(req) {
    return new Promise((resolve, reject) => {
        // console.log("请求添加的参数", req)
        // 添加类型：根节点
        if (req.type == 0) {
            new customSchemas.categoryModel({
                categoryName: req.categoryName,
                createTime: moment().format("YYYY-MM-DD HH:mm:ss"),
                lastModifyTime: moment().format("YYYY-MM-DD HH:mm:ss"),
            }).save(err => {
                if (err) {
                    console.log(err.message)
                    if (/duplicate/.test(err.message) === true) {
                        reject("分类名称不能重复！")
                    } else {
                        reject(err)
                    }
                } else {
                    resolve()
                }
            })
        } else if (req.type == 1) {
            if (req.parentId == '' || req.parentId == undefined) return reject("parentId不能为空")
            let child = new customSchemas.categoryModel({
                categoryName: req.categoryName,
                createTime: moment().format("YYYY-MM-DD HH:mm:ss"),
                lastModifyTime: moment().format("YYYY-MM-DD HH:mm:ss"),
                parentId: req.parentId
            })
            customSchemas.categoryModel.findByIdAndUpdate(req.parentId, {
                $addToSet: {
                    children: child
                }
            }, (err, ret) => {
                if (err) return rej(err)
                resolve()
            })
        } else {
            reject("需要指定添加的类型！")
        }

    })
}

function editCategory(body) {
    return new Promise((res, rej) => {
        console.log(body)
        if (body.id === undefined) rej("ID不能为空!")
        if (body.type == 0) {
            customSchemas.categoryModel.findByIdAndUpdate(body.id, {
                $set: {
                    "categoryName": body.categoryName,
                    "lastModifyTime": moment().format("YYYY-MM-DD HH:mm:ss"),
                }
            }, (err, docs) => {
                if (err) return rej(err)
                res()
            })
        } else if (body.type == 1) {
            // 更新嵌套数组中的某些字段，$占位符可以看做找到的符合条件的数据。
            console.log("子类编辑")
            customSchemas.categoryModel.updateMany({
                'children._id': mongoose.Types.ObjectId(body.id)
            }, {
                $set: {
                    'children.$.categoryName': body.categoryName,
                    'children.$.lastModifyTime': moment().format("YYYY-MM-DD HH:mm:ss")
                }
            }, (err, docs) => {
                console.log("找到的", docs)
                if (err) return rej(err)
                res()
            })
        }

    })
}

// 删除大类时，type0直接删，删除子类type1需要update指定$pull。
// 需要注意，在以id查询pull的时候，需要使用mongoose.Types.ObjectId转换一下字符串。
function deleteCategory(body) {
    return new Promise((resolve, reject) => {
        if (body.id === undefined || body.id === '') reject("ID不能为空!")
        if (body.type == 0) {
            customSchemas.categoryModel.findByIdAndRemove(body.id, (err, docs) => {
                if (err) {
                    reject(err)
                } else {
                    resolve()
                }
            })
        } else if (body.type == 1) {
            if (body.parentId === undefined || body.parentId === '') reject("parentId不能为空!")
            customSchemas.categoryModel.findByIdAndUpdate(body.parentId, {
                $pull: {
                    children: {
                        "_id": mongoose.Types.ObjectId(body.id)
                    }
                }
            }, (err, docs) => {
                if (err) return reject(err)
                resolve()
            })

        }

    })
}

module.exports = {
    // 通用
    getCommonList,
    createCommonData,
    editCommonData,
    deleteCommonData,

    // 树结构特殊方法
    getCategoryList,
    createCategory,
    editCategory,
    deleteCategory
}